home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
By Popular Request 2.0
/
By Popular Request 2.0 (Arsenal Computer).ISO
/
amiga_1
/
amnfrm55.lha
/
inform
/
release-note.txt
< prev
Wrap
Text File
|
1995-08-02
|
21KB
|
547 lines
What's New in Inform 5.5, v1502
-------------------------------
(5 July 1995)
Version 5.5 is the first upgrade of the Inform compiler to provide new
features (rather than just fix bugs) for about 10 months.
For the last year or so, my intention has been to keep the Inform language
stable, but to continually enhance the library. Although these additions do
change the language, they are hopefully minor and logical, and several have
long been asked for. Inform 5.5 removes no features of 5.4 (except in so
far as it tests for a few more definite errors, so some old but subtly wrong
code may not compile: this is probably a good thing). However, it does now
produce warnings if the source code uses obselete features (leftovers from
Inform 1 right up to those from Inform 5.4). The new syntax is so much
nicer that I suggest changing over to it rather than switching off these
warnings at the command line.
The short answer is: tidier object-name printing, more logical and flexible
syntax for creating arrays, tables of data, slightly better grammar
replacement, a switch statement and provision for compiling very much larger
games (up to twice the size of the previous maximum, which was pretty huge
anyway).
*** It is recommended that Inform 5.5 should only be used with ***
*** library release 5/10 and later ***
(there was a minor bug in 5/9 which can cause compilation errors: an
example of "old but subtly wrong code"). In any case, accompanying this
release is library 5/11.
0. Bugs fixed from v1405 (all minor)
-------------------------------------
(a) comments caused problems when coming between a loop construct (e.g.
"for (i=1:i<10:i++)") and its block of code.
(b) using the "box" command inside an embedded routine (which is seldom
sensible, actually!) sometimes produced mysterious compilation errors.
(c) the code for explicitly-defined string constants, such as
Constant Game "Lost Trifles of Bluffocom";
has been thoroughly rewritten, since the old method produced wrong
results in some cases (such as if a global variable had been
given as initial value a string, e.g. by: global Var="hello";).
(d) initial values like strings and dictionary words for global variables
(at declaration time) now work properly.
(e) removal of a foolish restriction rather than bug: string constants
had to be preceded by a # in usage, (e.g. print #Dragons_Name;) for no
good reason. (E.g., print Dragons_Name; now works.)
(f) the #r$RoutineName construction didn't work when RoutineName was
within the first 256 bytes of the code area (only library internals live
there, and this bug has never been observed in honest code!)
(g) actually, this is the same as in v. 5.4, but I seem to have forgotten
to publicise it: the function indirect(R); (to call the function with
address R, so for instance indirect(#r$MyFunction)) can now take an optional
second and third argument. indirect(R,x); calls function R with one
parameter, x, and indirect(R,x,y); calls it with two, x and y.
(h) the notoriously unhelpful (though happily rare) "a label has moved
between passes" error message has been rewritten to suggest the likely
cause: it now reads
An error has occurred just before this point with what Inform
thought was a constant. Perhaps it was a global variable used
before its definition in the code.
(i) local variables can't be called "sp" (this is the name of the stack
pointer, so crashes result) and an error is now produced if they are.
0'. Bugs fixed in, and additions made to, the beta-version
-----------------------------------------------------------
A beta-testing version of Inform 5.5 was (silently by me) put onto the
archive for porters to experiment with (though in the event many other
people found it). This version, v1501, included a serious bug (l) and
several improvements have been made since:
(j) the assembly opcode @set_colour now works (actually, this bug is a
year old, and was simultaneously found by two different people in the last
couple of months).
(k) values in switch statements are now allowed to take the form "x to y"
(for x<=v<=y), stolen from Modula-3 at Gareth Rees's suggestion.
(l) a bug in final file output caused incorrect game files to be
produced if no version-number had been explicitly set (it now by default
produces legal V5 files).
(m) details for the VMS port (for VAX or Alpha), the Linux, OS/2 and
Mac ports have been updated; the latter now includes a Macintosh
Programmer's Workshop version.
(n) it's difficult to compile dictionary words which contain apostrophes
(e.g., words such as "jemima's") as constants under I5.4; under I5.5,
apostrophes ' in dictionary words should now always be written with an ^.
For example, the constant 'isaac^s' refers to the word "isaac's".
(o) if you specify a property in an object description but give it no
data values, I5.5 now supplies a 0 word as value (5.4 used to compile an
empty list, which was logical but apt to confuse the interpreter).
(p) the grammar enhancements in (10) below were added.
(q) different file extensions for all of V3 to V8 inclusive can now be
made, if the port makes suitable #defines in header.h.
(r) giving a non-default output filename at the command line didn't
work in v1501, owing to a foolish bug.
(s) fuller details are given below of the V8 alterations needed to
"Zip".
(t) overflow of the buffer used for text-transcription (to make "proofs"
of the text in a game) is now checked for; previously this might have
caused memory (typically the symbols table) to be corrupted on very large
games when compiling with -r set.
1. Printing
------------
Recall that the "print" and "print_ret" commands take a list of items,
separated by commas, printing each in turn. (The latter then prints a
new-line and returns true.) The new preferred syntax for these items is one
of:
<expression> print this number
"string" print this string
char <expression> print the character this is the ASCII code of
object <expression> print the given object's true short name
(this shouldn't be used except by the Library,
as it will fail to notice the short_name routines
many objects provide)
(the) expression the definite article and short-name of this object
(The) expression the same, but capitalising the definite article
(a) expression the indefinite article and short-name
(name) expression just the short-name
(char) expression same as print char, for consistency
(number) expression print the number but in words, not numerals
(string) expression print the string at this (packed) address: good
for printing out property values which are
strings in double-quotes
(address) expression print the string at this byte address: good
for printing out dictionary words and little else
(Routine) expression print nothing: but call Routine(expression)
in the expectation that it will print something
These new features are cosmetic, but considerably tidy the look of code.
E.g., one would write
print_ret (The) x1, " explodes messily. Perhaps it was unwise to \
drop it into ", (the) x2, ".";
to produce, say,
The hand grenade explodes messily. Perhaps it was unwise to drop
it into the glassworks.
whereas in 5.4 it would have to have been
CDefArt(x1); print " explodes messily. Perhaps it was unwise to \
drop it into "; DefArt(x2); ".";
2. Global variables, tables and arrays
---------------------------------------
The whole syntax for declaring global variables has been tidied up and
extended. The new syntax for declaring a variable "frotz" is:
Global frotz; Ordinary variable, set to 0
Global frotz = <value>; ..., set to this value
Global frotz <array-type> <array-data>;
But since one very rarely wants to change the value of "frotz" in this case
(it will remain the address of the array throughout the game), the more usual
course is to declare
Array frotz <array-type> <array-data>;
which is identical in effect, except that "frotz" is now a constant. (This
can be convenient: it can now be quoted in other array definitions, for
instance, or as a property value.)
There are four types of array:
Syntax Pronounced Contents
-> byte array with entries written array->0 up to array->(n-1)
(can hold chars and numbers between 0 and 255)
--> word array with entries array-->0 up to array-->(n-1)
(can hold any Inform number)
string string a byte array, in which byte 0 holds the number of
data entries in the array
table table a word array, in which word 0 holds the number of
data entries in the array
The array data can also be given in several ways:
a single value - allocate this many zero entries;
two or more values (divided by spaces) - these are the entries;
a string in double-quotes - the entries are the ASCII values of the
characters of this string, in sequence;
or, as
[; <value-1>; ....; <value-n>; ];
which makes the entries these given values. Semicolons in between the braces
are ignored. (The usefulness of this is that very long declarations, which
would otherwise overflow Inform source code lines, can be made.)
These initial values can be any legal constant (for the first time this
allows dictionary words and routine names): e.g.,
105 "a quoted string" 'c' 'dictionary' #r$RoutineName
For instance,
Array frotz -> 20;
makes an array of 20 bytes, entries of which can be read or written as
frotz->0 ... frotz->19. The initial values are all zero. Whereas:
Array frotz -> 4 8 12 16 20;
makes an array of 5 bytes, initially holding these five values.
Array colours --> "Red" "Yellow" "Blue";
...
print (string) colours-->1;
will print "Yellow".
Array frotz string "blorple";
makes frotz point to an array with contents
7 'b' 'l' 'o' 'r' 'p' 'l' 'e'
(This differs from Array frotz -> "blorple" in creating the initial 7.)
A typical large table might have the form of:
Array Holidays table
[; "New Year's Day" "Twelfth Night";
"Ash Wednesday" "Good Friday";
"Martin Luther King Day";
];
For instance, the names of songs played by the radio in "Curses" occupies a
(pretty enormous) table, and
print (string) RadioSongs-->(random(RadioSongs-->0));
prints out a random name from it.
In older versions of Inform the keywords "data", "initial" and "initstr"
would have been used to initialise byte arrays suitably, and (annoyingly)
word arrays couldn't be initialised to non-zero values at all. These
keywords still work, but are no longer needed.
3. Function calls
------------------
Can now take up to 7 arguments, instead of being restricted to 3.
(Except in version-3 games, but I hope everyone's gone over to Advanced
(version-5) now.)
4. Switch statements
---------------------
Inform now has a "switch" statement similar to that of C. That is,
switch(expression)
{ value1: ...
value2: ...
...
default: ...
}
evaluates the expression, and executes the first ... code if it has value1,
the second ... if it has value2, and so on: if it has none of the values
given, the default ... code is run. (The "default" clause is optional,
but if present must be the last clause.)
(Unlike in C, there is no "case fall-through"; that is, once the value1
code is executed, control automatically resumes from after the end of the
switch statement.)
Each value can in fact be a list of values, comma-separated. A value
can either be a single Inform constant or something in the form
constant1 to constant2
(the range being inclusive). So, for example:
switch(random(6))
{ 1: "A snake slithers.";
2 to 4: "An elephant bellows.";
default: "The jungle is ominously silent.";
}
The "default" clause can now also be put into embedded routines, like
before rules. So, for instance, a room can have the "before" value
before
[; Jump: "The ceiling is too low.";
Look, Inv, Wait: ;
default: "An invisible force holds you inactive.";
];
and the "default" rule is run if none of the others are. Note that the
Look, Inv and Wait actions are unaffected as we have explicitly done nothing
to them.
5. Abbreviate directive
------------------------
The Abbreviate directive can now take a list of abbreviation strings, not
just one at a time (and this saves writing out "Abbreviate" 64 times). E.g.
Abbreviate
". " ", " " the " "The" "You" "ing" "you" "and" "ight" "with"
"all" "'s no" "which" "It is" " th" " no" "t o" "e s" "e i"
" to" "e o" "e a" " ma" "t i" " fi" "e w" " for" " con" " ba"
"d o" " ro" " di" " can" " lo" "t s" "t w" " com" " ho"
" ga" "tion" " from" " ha" "ter" " ea" "This" " hi" " pr" " un"
"d s" " fa" "urs" "'s ~" " ex" "der" "d a" " gr" " cl"
"d i" " po" " door" "her" " a ";
is a plausible set of abbreviation strings, saving about 20K on a 256K game
file when Inform is compiling with the "economy" switch -e set.
6. Testing the version number
------------------------------
A special rule now applies to the Ifdef directive.
#Ifdef VN_****;
...
#Endif;
where **** is the four-digit number n, will now compile the code ... exactly
if the current Inform version number is at least n. Thus,
#Ifdef VN_1501; print "The all new Inform show!^"; #Endif;
compiles only under this and later updates.
7. More flexible < > construct
-------------------------------
Previously, constructions like
<Action noun second>;
were rather restricted, in that Action always had to be an action name
and noun and second couldn't be compound expressions. The latter restriction
is now removed, and the former almost so: if Action is given in brackets
(...) then it's worked out as an expression in the usual way. (Brackets
are needed to tell Inform that the first word shouldn't be tested as a
constant with ## in front, which is what it does with action names.) So,
for instance,
<< (magic_action(frotz_spell)) noun.door_dir memory.number >>;
will now compile. All previously-allowed < > and << >> expressions should
compile just as they always did.
8. Versions 7 and 8
--------------------
Two new types of story file are implemented: versions 7 and 8, newly
created for the purpose. (Inform can produce version 6, but this isn't
recommended for text-only games as version 6 is very hard to fully interpret
because of complex graphical features.)
Version 8 is the one recommended for use, if a game of over 256K is
required: it runs up to 512K in length. Inform syntax is fully portable
between version-5 (the default) and version-8; all you need to do is to
compile with -v8 set.
At present versions 7 and 8 are not interpreted by the interpreters in
public circulation. However, V8 is particularly easy to add to Mark
Howell's "Zip" interpreter; see the end of this file. A fairly large V8
file (a V8 form of the author's new game "Jigsaw") will soon be available
for experiment.
Support for these new versions should percolate through the public domain
in due course, since it's so easily coded, but if you're in a hurry you need
only distribute your game with a suitably doctored interpreter.
It should be added that a 512K Inform game would be gargantuan, 2.5 times
the size of "Curses" (which is itself large as games go) - easily large
enough to code the entire Zork and Enchanter trilogies into one.
9. At the command line, and file inclusion
-------------------------------------------
Apart from -v8 (and -v7), there are two new command line switches: to
change the error message style to Microsoft standard format, and to suppress
warnings about obselete usages.
There is one new memory command, $huge, which is an abbreviation for
lots of large memory settings and saves bother when games have become pretty
enormous.
If a command line argument begins with a plus sign +, then the rest of that
word is taken to be a directory in which the Library can be found. (This is
convenient so that only one copy of the Library need be kept, which several
projects in different directories can make use of.) E.g., I use something
like
inform -Tdcx $huge +Library curses/curses games/curses.z5
The Include directive has a convenient new feature: if the file-name to
include begins with a >, like so
Include ">endgame";
then the file "endgame" is sought from the same directory as the one doing
the inclusion. (Otherwise, if it has a / in, it's treated literally, and if
not it's sought from the library directory.) This is much less trouble
when a game's source code is segmented into many files, as it usually is
for large projects.
10. Grammar replacement
------------------------
In library grammar, some verbs have many synonyms: for instance,
"attack" "break" "smash" "hit" "fight" "wreck" "crack"
"destroy" "murder" "kill" "torture" "punch" "thump"
are all treated as identical. But you might want to distinguish between
murder and lesser crimes. For this, try
Extend only "murder" "kill" replace
* animate -> Murder;
The keyword 'only' tells Inform to extract the two verbs "murder" and
"kill". These then become a new verb which is initially an identical copy
of the old one, but then 'replace' tells Inform to throw that away in favour
of an entirely new grammar.
Similarly,
Extend only "get" * "with" "it" -> Sing;
makes "get" behave exactly like "take" (as usual) except that it also
recognises "with it", so that "get with it" makes the player sing but "take
with it" doesn't.
You can now also add new verb synonyms. For instance,
Verb "acquire" "grab" = "take";
gives the "take" verb two new synonyms.
Appendix: Adding Version 8 support to the "Zip" interpreter
-----------------------------------------------------------
Only one routine need be changed, "configure". In my copy of the source (10
March 93) it now looks as below (note that in my copy only one if statement
has been added).
/*
* configure
*
* Initialise global and type specific variables.
*
*/
#ifdef __STDC__
static void configure (zbyte_t min_version, zbyte_t max_version)
#else
static void configure (min_version, max_version)
zbyte_t min_version;
zbyte_t max_version;
#endif
{
zbyte_t header[PAGE_SIZE];
read_page (0, header);
datap = header;
h_type = get_byte (H_TYPE);
if (h_type < V4) {
story_scaler = 2;
story_shift = 1;
property_mask = P3_MAX_PROPERTIES - 1;
property_size_mask = 0xe0;
} else {
story_scaler = 4;
story_shift = 2;
property_mask = P4_MAX_PROPERTIES - 1;
property_size_mask = 0x3f;
}
if (h_type == 8) /* This is my amendment for V8... */
{ h_type=V5;
story_scaler = 8;
story_shift = 3;
} /* ...ending here. */
if (h_type < min_version || h_type > max_version
|| (get_byte (H_CONFIG) & CONFIG_BYTE_SWAPPED))
fatal ("wrong game or version");
h_config = get_byte (H_CONFIG);
h_version = get_word (H_VERSION);
h_data_size = get_word (H_DATA_SIZE);
h_start_pc = get_word (H_START_PC);
h_words_offset = get_word (H_WORDS_OFFSET);
h_objects_offset = get_word (H_OBJECTS_OFFSET);
h_globals_offset = get_word (H_GLOBALS_OFFSET);
h_restart_size = get_word (H_RESTART_SIZE);
h_flags = get_word (H_FLAGS);
h_synonyms_offset = get_word (H_SYNONYMS_OFFSET);
h_file_size = get_word (H_FILE_SIZE);
if (h_file_size == 0)
h_file_size = get_story_size ();
h_checksum = get_word (H_CHECKSUM);
h_alternate_alphabet_offset = get_word (H_ALTERNATE_ALPHABET_OFFSET);
datap = NULL;
}/* configure */